const { MemberLevel, User, SystemLog } = require('../models');
const { AppError } = require('../middlewares/errorHandler');
const { logger } = require('../utils/logger');
const { Op } = require('sequelize');

class MemberLevelController {
  /**
   * 创建会员等级
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async createMemberLevel(ctx) {
    const {
      name,
      level,
      pointsRequired,
      benefits,
      description,
      icon,
      color,
      discountRate,
      monthlyPoints,
      specialPrivileges
    } = ctx.request.body;
    const userId = ctx.state.user.id;

    // Check if level already exists
    const existingLevel = await MemberLevel.findOne({
      where: {
        [Op.or]: [
          { name },
          { level }
        ]
      }
    });

    if (existingLevel) {
      throw new AppError(400, 'Member level with this name or level number already exists');
    }

    // Create member level
    const memberLevel = await MemberLevel.create({
      name,
      level,
      pointsRequired,
      benefits,
      description,
      icon,
      color,
      discountRate,
      monthlyPoints,
      specialPrivileges,
      status: 'active'
    });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'create_member_level',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Member level created: ${name} (Level ${level})`
    });

    ctx.status = 201;
    ctx.body = {
      status: 'success',
      data: { memberLevel }
    };
  }

  /**
   * 更新会员等级
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateMemberLevel(ctx) {
    const { id } = ctx.params;
    const {
      name,
      level,
      pointsRequired,
      benefits,
      description,
      icon,
      color,
      discountRate,
      monthlyPoints,
      specialPrivileges,
      status
    } = ctx.request.body;
    const userId = ctx.state.user.id;

    const memberLevel = await MemberLevel.findByPk(id);
    if (!memberLevel) {
      throw new AppError(404, 'Member level not found');
    }

    // Check if new name or level already exists
    if (name !== memberLevel.name || level !== memberLevel.level) {
      const existingLevel = await MemberLevel.findOne({
        where: {
          [Op.and]: [
            { id: { [Op.ne]: id } },
            {
              [Op.or]: [
                { name },
                { level }
              ]
            }
          ]
        }
      });

      if (existingLevel) {
        throw new AppError(400, 'Member level with this name or level number already exists');
      }
    }

    // Update member level
    await memberLevel.update({
      name,
      level,
      pointsRequired,
      benefits,
      description,
      icon,
      color,
      discountRate,
      monthlyPoints,
      specialPrivileges,
      status
    });

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'update_member_level',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Member level updated: ${name} (Level ${level})`
    });

    ctx.body = {
      status: 'success',
      data: { memberLevel }
    };
  }

  /**
   * 删除会员等级
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async deleteMemberLevel(ctx) {
    const { id } = ctx.params;
    const userId = ctx.state.user.id;

    const memberLevel = await MemberLevel.findByPk(id);
    if (!memberLevel) {
      throw new AppError(404, 'Member level not found');
    }

    // Check if any users are at this level
    const userCount = await User.count({ where: { memberLevelId: id } });
    if (userCount > 0) {
      throw new AppError(400, 'Cannot delete member level with existing users');
    }

    await memberLevel.destroy();

    // Log the action
    await SystemLog.create({
      type: 'operation',
      action: 'delete_member_level',
      userId,
      ipAddress: ctx.ip,
      userAgent: ctx.headers['user-agent'],
      description: `Member level deleted: ${memberLevel.name} (Level ${memberLevel.level})`
    });

    ctx.body = {
      status: 'success',
      message: 'Member level deleted successfully'
    };
  }

  /**
   * 获取会员等级列表
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getMemberLevels(ctx) {
    const { status } = ctx.query;
    const where = {};

    if (status) where.status = status;

    const memberLevels = await MemberLevel.findAll({
      where,
      order: [['level', 'ASC']]
    });

    ctx.body = {
      status: 'success',
      data: { memberLevels }
    };
  }

  /**
   * 获取单个会员等级
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getMemberLevel(ctx) {
    const { id } = ctx.params;

    const memberLevel = await MemberLevel.findByPk(id, {
      include: [{
        model: User,
        attributes: ['id', 'username', 'email', 'points'],
        limit: 10
      }]
    });

    if (!memberLevel) {
      throw new AppError(404, 'Member level not found');
    }

    ctx.body = {
      status: 'success',
      data: { memberLevel }
    };
  }

  /**
   * 更新会员等级状态
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async updateMemberLevelStatus(ctx) {
    const { id } = ctx.params;
    const { status } = ctx.request.body;
    const userId = ctx.state.user.id;

    const memberLevel = await MemberLevel.findByPk(id);
    if (!memberLevel) {
      throw new AppError(404, 'Member level not found');
    }

    // 验证状态值
    const validStatuses = ['active', 'inactive', 'deprecated'];
    if (!validStatuses.includes(status)) {
      throw new AppError(400, '无效的状态值');
    }

    // 如果要停用会员等级，检查是否有用户正在使用
    if (status === 'inactive') {
      const usersCount = await User.count({
        where: { memberLevelId: id }
      });

      if (usersCount > 0) {
        throw new AppError(400, '该会员等级正在被用户使用，无法停用');
      }
    }

    await memberLevel.update({ 
      status,
      updatedBy: userId,
      lastStatusChange: new Date()
    });

    // 记录操作日志
    await SystemLog.create({
      action: 'update_member_level_status',
      operator: userId,
      target_type: 'member_level',
      target_id: id,
      details: { 
        before: memberLevel.status,
        after: status
      }
    });

    ctx.body = {
      status: 'success',
      data: {
        memberLevel
      }
    };
  }

  /**
   * 获取会员等级用户列表
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async getMemberLevelUsers(ctx) {
    const { id } = ctx.params;
    const { page = 1, limit = 10 } = ctx.query;

    const memberLevel = await MemberLevel.findByPk(id);
    if (!memberLevel) {
      throw new AppError(404, 'Member level not found');
    }

    const offset = (page - 1) * limit;
    const users = await User.findAndCountAll({
      where: { memberLevelId: id },
      attributes: ['id', 'username', 'email', 'points', 'createdAt'],
      limit: parseInt(limit),
      offset: parseInt(offset),
      order: [['points', 'DESC']]
    });

    ctx.body = {
      status: 'success',
      data: {
        users: users.rows,
        pagination: {
          total: users.count,
          page: parseInt(page),
          totalPages: Math.ceil(users.count / limit)
        }
      }
    };
  }

  /**
   * 检查用户等级升级
   * @param {Object} ctx - 上下文
   * @returns {Promise<void>}
   */
  async checkUserLevelUpgrade(ctx) {
    const { userId } = ctx.params;
    const operatorId = ctx.state.user.id;

    const user = await User.findByPk(userId, {
      include: [{ model: MemberLevel }]
    });

    if (!user) {
      throw new AppError(404, 'User not found');
    }

    // Get all active levels ordered by points required
    const levels = await MemberLevel.findAll({
      where: { status: 'active' },
      order: [['pointsRequired', 'ASC']]
    });

    // Find the highest level the user qualifies for
    let newLevel = null;
    for (const level of levels) {
      if (user.points >= level.pointsRequired) {
        newLevel = level;
      } else {
        break;
      }
    }

    if (!newLevel || (user.memberLevelId && newLevel.id === user.memberLevelId)) {
      ctx.body = {
        status: 'success',
        data: {
          currentLevel: user.MemberLevel,
          qualifiesForUpgrade: false
        }
      };
      return;
    }

    // Update user's level if it's different
    if (!user.memberLevelId || newLevel.id !== user.memberLevelId) {
      await user.update({ memberLevelId: newLevel.id });

      // Log the action
      await SystemLog.create({
        type: 'operation',
        action: 'member_level_upgrade',
        userId: operatorId,
        ipAddress: ctx.ip,
        userAgent: ctx.headers['user-agent'],
        description: `User ${user.username} upgraded to level ${newLevel.name}`
      });
    }

    ctx.body = {
      status: 'success',
      data: {
        previousLevel: user.MemberLevel,
        newLevel,
        qualifiesForUpgrade: true
      }
    };
  }
}

module.exports = new MemberLevelController(); 